using System;
using System.Collections;
using System.Diagnostics;
using System.IO;


namespace Pegasus.Diagnostics.Telnet
{
	/// <summary>
	/// Implements the Trace command for the telnet service
	/// </summary>
	internal class CommandTrace : ITelnetCommand
	{
		/// <summary>
		/// Default Constructor
		/// </summary>
		public CommandTrace()
		{
		}

		/// <summary>
		/// The names of the command that the user types in.
		/// </summary>
		public string Command
		{
			get
			{
				return "trace";
			}
		}

		/// <summary>
		/// Any short cut commands or key (i.e. quit uses q and exit)
		/// </summary>
		public string[] CommandShortCuts
		{
			get
			{
				return new string[] { "tr" };
			}
		}

		/// <summary>
		/// Execute the command.
		/// </summary>
		/// <param name="writer">Text stream to write to</param>
		/// <param name="args">Additional parameters that the user typed in.</param>
		public void ExecCommand( TextWriter writer, string[] args )
		{
			switch( args.Length )
			{
				case 0:
					ShowTracing( writer, null );
					break;

				case 1:
					ShowTracing( writer, args [ 0 ] );
					break;

				case 2:
					SetTracing( writer, args[ 0 ], args[ 1 ], null );
					break;

				case 3:
					SetTracing( writer, args[ 0 ], args[ 1 ], args[ 2 ] );
					break;

				default:
					writer.WriteLine( "Trace called with invalid number of arguments..." );
					ShowDetailedHelp( writer );
					break;
			}
		}

		/// <summary>
		/// Show a single line of help about the command
		/// </summary>
		/// <returns>Single line brief description of command</returns>
		public string GetHelp()
		{
			return "View and set the status of the different objects that support tracing.";
		}

		/// <summary>
		/// Show a the full usage help about the command
		/// </summary>
		/// <param name="writer">Text stream to write to</param>
		public void ShowDetailedHelp( TextWriter writer )
		{
			writer.WriteLine( "Command: trace" );
			writer.WriteLine( "Usage: trace [ name | all ] [ tracelevel ] [ instance ]" );
			writer.WriteLine();
			writer.WriteLine( "Description:  View and set the status of the different" );
			writer.WriteLine( "objects that support tracing." );
			writer.WriteLine();
			writer.WriteLine( "Trace Levels: verbose, info, warn, error, or off." );
			writer.WriteLine();
			writer.WriteLine( "Instance: The application/object specific instance string" );
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="writer"></param>
		/// <param name="switchName"></param>
		private void ShowTracing( TextWriter writer, string switchName )
		{
			int count = 0;
			
			if( switchName != null )
			{
				switchName = switchName.ToLower();
			}

			writer.WriteLine();
			writer.WriteLine( "Level     Name" );
			writer.WriteLine();

// Disable the warning that the TraceSwitchEx class is Obsolete
#pragma warning disable 618
			foreach( TraceSwitchEx traceSwitch in TraceSwitchEx.TraceSwitches.Values )
			{
				if( switchName == null || traceSwitch.DisplayName.ToLower().StartsWith( switchName ) )
				{
					writer.WriteLine( "{0,-7} {1}", TraceSwitchEx.GetLevelName( traceSwitch.Level ), traceSwitch.DisplayName );
					writer.WriteLine( "        " + traceSwitch.Description );

					if( traceSwitch.InstanceName != null )
					{
						writer.WriteLine( "        Instence filter on. ({0})", traceSwitch.InstanceName );
					}
					else
					{
						writer.WriteLine( "        Instence filter off." );
					}
					
					writer.WriteLine();

					count++;
				}
			}
#pragma warning restore 618

			if( count == 0 )
			{
				writer.WriteLine( "Not trace switches found." );
				writer.WriteLine();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="writer"></param>
		/// <param name="switchName"></param>
		/// <param name="levelName"></param>
		/// <param name="instance"></param>
		private void SetTracing( TextWriter writer, string switchName, string levelName, string instance  )
		{
			int count = 0;
// Disable the warning that the TraceSwitchEx class is Obsolete
#pragma warning disable 618
			TraceLevel newLevel = TraceSwitchEx.GetLevel( levelName );
#pragma warning restore 618
			switchName = switchName.ToLower();

			writer.WriteLine();

// Disable the warning that the TraceSwitchEx class is Obsolete
#pragma warning disable 618
			foreach( TraceSwitchEx traceSwitch in TraceSwitchEx.TraceSwitches.Values )
			{
				if( traceSwitch.DisplayName.ToLower().StartsWith( switchName ) ||
					switchName == "all" )
				{
					TraceLevel oldLevel = traceSwitch.Level;
					traceSwitch.Level = newLevel;
					traceSwitch.InstanceName = instance;

					writer.WriteLine( "Changed {0} from {1} to {2}, instance name {3}",
						traceSwitch.DisplayName,
						TraceSwitchEx.GetLevelName( oldLevel ),
						TraceSwitchEx.GetLevelName( newLevel ),
						traceSwitch.InstanceName != null ? traceSwitch.InstanceName : "(none)" );

					count++;
				}
			}
#pragma warning restore 618

			if( count > 0 )
			{
				if( switchName == "all" )
				{
					switchName = null;
				}

				ShowTracing( writer, switchName );
			}
			else
			{
				writer.WriteLine( "Not trace switches found." );
			}
		}
	}
}
